﻿//------------------------------------------------------------------------------
//  Namespace: FruitVentDesign.Utils
//  
//  Function： N/A
//  Name： PrinterHelper
//  
//  Ver       Time                     Author
//  0.10      2021/6/28 16:06:01      FruitVent
//
//  此代码版权归作者本人FruitVent所有
//  源代码使用协议遵循本仓库的开源协议及附加协议，若本仓库没有设置，则按MIT开源协议授权
//  CSDN博客：https://blog.csdn.net/weixin_39552347
//  源代码仓库：https://gitee.com/fruitvent
//  感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace FruitVentDesign.Utils
{
    public class PrinterHelper
    {
        //调用win api将指定名称的打印机设置为默认打印机
        [DllImport("winspool.drv")]
        public static extern bool SetDefaultPrinter(String Name);

        private static PrintDocument fPrintDocument = new PrintDocument();
        //获取本机默认打印机名称
        public static String DefaultPrinter()
        {
            return fPrintDocument.PrinterSettings.PrinterName;
        }

        //获得系统中的打印机列表
        public static List<String> GetLocalPrinters()
        {
            List<String> fPrinters = new List<String>
            {
                DefaultPrinter() //默认打印机始终出现在列表的第一项
            };
            foreach (String fPrinterName in PrinterSettings.InstalledPrinters)
            {
                if (!fPrinters.Contains(fPrinterName))
                {
                    fPrinters.Add(fPrinterName);
                }
            }
            return fPrinters;
        }

        /// <summary>
        /// 获取landscapes
        /// </summary>
        /// <returns></returns>
        public static Dictionary<bool, string> GetLandscapes()
        {
            Dictionary<bool, string> landscapes = new Dictionary<bool, string>();
            landscapes.Add(false, "纵向");
            landscapes.Add(true, "横向");

            return landscapes;
        }

        /// <summary>
        /// 获取打印机纸张大小列表
        /// </summary>
        /// <returns></returns>
        public static System.Drawing.Printing.PrinterSettings.PaperSizeCollection GetPaperSizes()
        {
            System.Drawing.Printing.PrinterSettings Ps = new System.Drawing.Printing.PrinterSettings();
            System.Drawing.Printing.PrinterSettings.PaperSizeCollection paperSizeCollection = Ps.PaperSizes;

            return paperSizeCollection;
        }

        private static System.Drawing.Image PrintImg { get; set; } = null;
        private static string Watermark = null;

        /// <summary>
        /// 调用打印机打印图片 landscape横向打印为true
        /// </summary>
        public static void PrintImage(System.Drawing.Image img, bool landscape, PaperSize paperSize, string watermark)
        {
            Watermark = watermark;
            PrintImg = new Bitmap(img);
            PrintDialog PD = new PrintDialog();
            System.Drawing.Printing.PrinterSettings Ps = new System.Drawing.Printing.PrinterSettings();
            PD.PrinterSettings = Ps;
            PrintDocument document = new PrintDocument();
            //System.Drawing.Printing.PageSettings pageSettings = new PageSettings();
            //pageSettings.Margins = new Margins(0, 0, 0, 0);
            //pageSettings.PaperSize = paperSize;
            //pageSettings.Landscape = landscape;
            //document.DefaultPageSettings = pageSettings;
            document.DefaultPageSettings.PaperSize = paperSize;
            document.DefaultPageSettings.Landscape = landscape;
            document.DefaultPageSettings.Margins.Top = 0;
            document.DefaultPageSettings.Margins.Bottom = 0;
            document.DefaultPageSettings.Margins.Left = 0;
            document.DefaultPageSettings.Margins.Right = 0;
            PD.PrinterSettings.DefaultPageSettings.Margins.Top = 0;
            PD.PrinterSettings.DefaultPageSettings.Margins.Bottom = 0;
            PD.PrinterSettings.DefaultPageSettings.Margins.Left = 0;
            PD.PrinterSettings.DefaultPageSettings.Margins.Right = 0;
            document.PrintPage += Document_PrintPage;
            document.DocumentName = "打印图像";
            document.Print();
            PD.Document = document;
        }

        private static void Document_PrintPage(object sender, PrintPageEventArgs e)
        {
            // 根据纸张大小和方向，读取图片，修改图片大小
            int height = e.MarginBounds.Height;
            int width = e.MarginBounds.Width;

            // Trace.WriteLine($"height:{height},width:{width}");

            using(Image newImage = ReziseImage(PrintImg, width, height))
            {
                int heightDifference = height - newImage.Height;
                int widthDifference = width - newImage.Width;

                //Trace.WriteLine($"heightDifference:{heightDifference},widthDifference:{widthDifference}");

                double x = 0D + e.MarginBounds.Left;
                if (widthDifference > 0)
                {
                    x = (widthDifference / 2D) + e.MarginBounds.Left;
                }

                double y = 0D + e.MarginBounds.Top;
                if (heightDifference > 0)
                {
                    y = (heightDifference / 2D) + e.MarginBounds.Top;
                }

                //Trace.WriteLine($"x:{x},y:{y}");

                using(System.Drawing.Image img = new Bitmap(PrintImg))
                {
                    e.Graphics.DrawImage(img,
                    new System.Drawing.Rectangle((int)x, (int)y, newImage.Width, newImage.Height),
                    0,
                    0,
                    img.Width,
                    img.Height,
                    GraphicsUnit.Pixel);
                    if (!string.IsNullOrEmpty(Watermark))
                    {
                        using (System.Drawing.Font font = new System.Drawing.Font("微软雅黑", 120))
                        {
                            double len = Math.Sqrt(Math.Pow(height, 2) + Math.Pow(width, 2));
                            e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                            System.Drawing.Font goodFont = FindFont(e.Graphics, Watermark, (float)(len / 24), font);
                            System.Drawing.SizeF fontRealSize = e.Graphics.MeasureString(Watermark, goodFont);
                            int count = Convert.ToBoolean((int)Math.Ceiling(height / fontRealSize.Width) & 1) ? (int)Math.Ceiling(height / fontRealSize.Width) + 1 : (int)Math.Ceiling(height / fontRealSize.Width);
                            e.Graphics.RotateTransform(-45);
                            for (int i = -count / 2; i <= count / 2; i += 2)
                            {
                                for (int j = 0; j <= 24; j += 4)
                                {
                                    e.Graphics.DrawString(
                                        Watermark,
                                        goodFont,
                                        new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(30, 51, 51, 51)),
                                        new System.Drawing.PointF((float)(i * fontRealSize.Width), (float)(j * fontRealSize.Height))
                                    );
                                }
                            }
                        }
                    }
                    e.HasMorePages = false;
                }
            } 
        }

        // This function checks the room size and your text and appropriate font
        //  for your text to fit in room
        // PreferedFont is the Font that you wish to apply
        // Room is your space in which your text should be in.
        // LongString is the string which it's bounds is more than room bounds.
        private static System.Drawing.Font FindFont(System.Drawing.Graphics g, string longString, float len, System.Drawing.Font PreferedFont)
        {
            // you should perform some scale functions!!!
            System.Drawing.SizeF RealSize = g.MeasureString(longString, PreferedFont);
            float ScaleRatio = len / RealSize.Height;

            float ScaleFontSize = PreferedFont.Size * ScaleRatio;

            return new System.Drawing.Font(PreferedFont.FontFamily, ScaleFontSize);
        }

        /// <summary>
        /// 缩放图片宽高
        /// </summary>
        /// <param name="img"></param>
        /// <param name="maxWidth"></param>
        /// <param name="maxHeight"></param>
        /// <returns></returns>
        private static System.Drawing.Image ReziseImage(System.Drawing.Image img, int maxWidth, int maxHeight)
        {
            double xRatio = (double)img.Width / maxWidth;
            double yRatio = (double)img.Height / maxHeight;
            double ratio = Math.Max(xRatio, yRatio);
            int nnx = (int)Math.Floor(img.Width / ratio);
            int nny = (int)Math.Floor(img.Height / ratio);
            Bitmap cpy = new Bitmap(nnx, nny, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            using (Graphics gr = Graphics.FromImage(cpy))
            {
                gr.Clear(System.Drawing.Color.Transparent);

                gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                gr.DrawImage(img,
                    new System.Drawing.Rectangle(0, 0, nnx, nny),
                    new System.Drawing.Rectangle(0, 0, img.Width, img.Height),
                    GraphicsUnit.Pixel);

            }

            return cpy;
        }
    }
}
